package com.yuuzy.dao;

import com.alibaba.druid.util.StringUtils;
import com.yuuzy.model.Buy_Fund;
import com.yuuzy.model.Client;
import com.yuuzy.model.Fund;
import com.yuuzy.utils.DBUtils;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;

import java.sql.Connection;
import java.sql.Date;
import java.sql.SQLException;
import java.util.List;

public class Buy_FundDAO extends BasicDAO<Buy_Fund> {
    private QueryRunner qr = new QueryRunner();

    /**
     * 查询购买基金的数据
     *
     * @param buy_fund 待查询的购买基金类（传入产品id和客户id，不传入默认查询全部记录）
     * @return 查询到的购买基金类集
     */
    public List<Buy_Fund> queryBuy_Fund(Buy_Fund buy_fund) {
        StringBuilder sb = new StringBuilder("select * from buy_fund");
        if (buy_fund.getClient_id() != null && buy_fund.getFund_id() != null) {
            //根据用户id查询和基金id查询
            sb.append(" and client_id = ").append(buy_fund.getClient_id());
            sb.append(" and fund_id = ").append(buy_fund.getFund_id());
        }
        String sql = sb.toString().replaceFirst("and", "where");
        return queryMulti(sql, Buy_Fund.class);
    }

    /**
     * 增加购买基金记录
     *
     * @param buy_fund 待传入的购买基金实体
     * @return 受影响的行数
     */
    public int insertBuy_Fund(Buy_Fund buy_fund) {
        String sql = "INSERT INTO finance.buy_fund(fund_id,client_id,buy_fund_time,buy_fund_quantity,buy_fund_assetstatus,buy_fund_earnings) VALUES (?,?,?,?,?,?)";
        return update(sql, buy_fund.getFund_id(), buy_fund.getClient_id(), buy_fund.getBuy_fund_time(), buy_fund.getBuy_fund_quantity(), buy_fund.getBuy_fund_assetstatus(), buy_fund.getBuy_fund_earnings());
    }

    /**
     * 删除购买基金的数据
     *
     * @param buy_fund 待删除的购买基金类（必须包含客户id和基金id）
     * @return 受影响的行数
     */
    public int deleteBuy_Fund(Buy_Fund buy_fund) {
        StringBuilder sb = new StringBuilder("DELETE FROM buy_fund");
        if (buy_fund.getClient_id() != null && buy_fund.getFund_id() != null) {
            sb.append(" and client_id = ").append(buy_fund.getClient_id());
            sb.append(" and buy_fund_id = ").append(buy_fund.getFund_id());
        }
        String sql = sb.toString().replaceFirst("and", "where");
        return update(sql);
    }

    /**
     * 更新购买基金记录
     *
     * @param buy_fund 待更新的购买基金类
     * @return 受影响的行数
     */
    public int updateBuy_Fund(Buy_Fund buy_fund) {
        //客户id和基金id不能更改
        StringBuilder sb = new StringBuilder("UPDATE buy_fund SET");
        if (buy_fund.getBuy_fund_time() != null) {
            //如果购买日期字段存在
            sb.append(" ,buy_fund_time = '").append(buy_fund.getBuy_fund_time()).append("'");
        }
        if (buy_fund.getBuy_fund_quantity() != null) {
            //如果数量字段存在
            sb.append(" ,buy_fund_quantity = ").append(buy_fund.getBuy_fund_quantity());
        }
        if (!StringUtils.isEmpty(buy_fund.getBuy_fund_assetstatus())) {
            //如果状态字段存在
            sb.append(" ,buy_fund_assetstatus = '").append(buy_fund.getBuy_fund_assetstatus()).append("'");
        }
        if (buy_fund.getBuy_fund_earnings() != null) {
            //如果收益字段存在
            sb.append(" ,buy_fund_earnings = ").append(buy_fund.getBuy_fund_earnings());
        }
        String sql = sb.append(" WHERE client_id = ? and fund_id = ?").toString().replaceFirst(",", "");
        return update(sql, buy_fund.getClient_id(), buy_fund.getFund_id());
    }

    /*
    购买基金
    设计思路：
    传入一个客户类，必须包含用户名和密码
    传入一个基金类，必须包含购买的基金id
    传入一个int类型参数，指明购买的基金份数
    返回一个Buy_Fund类

    （1）调用BanKCardDAO中的查询方法，获得完整的银行卡对象
    （2）调用FundDAO中的查询方法，获得完整的基金对象
    （3）先判断remain = （账户余额-基金金额*购买份数）是否大于0，若小于0，结束进程,返回null
    （4）若大于0，先查找表中是否有此类购买基金对象的记录，若有没有，则：
    （4.1）创建一个Buy_Fund类，将基本信息存入，并执行以下事务：
        向buy_fund表中增加一条记录
        修改客户账户内余额
        结束事务，返回创建好的Buy_Fund类
     若已存在此类基金对象的记录，则：
     （4.2）执行以下事务：
        更新buy_fund对象中的quantity字段
        修改客户账户内余额
        结束事务，返回修改好的Buy_Fund类
     */

    /**
     * @param client   客户类
     * @param fund     客户拟购买的基金类
     * @param quantity 购买数量
     * @return 购买基金类
     */
    public Buy_Fund buyFund(Client client, Fund fund, int quantity) {
        ClientDAO clientDAO = new ClientDAO();
        //（1）调用ClientDAO中的查询方法，获得完整的客户对象
        List<Client> clientList = clientDAO.queryClient(client);
        client = clientList.get(0);//去除第一个客户，也只可能有一个客户
        //（2）调用FundDAO中的查询方法，获得完整的基金对象
        List<Fund> fundList = new FundDAO().queryFund(fund);
        fund = fundList.get(0);//取出第一项基金，也只可能有一项基金
        //（3）先判断remain = （账户余额-基金金额*购买份数）是否大于0
        double remain = client.getClient_balance() - fund.getFund_amount() * quantity;
        if (remain < 0) {
            //余额小于0，购买失败
            System.out.println("余额不足");
            return null;
        }
        //（4）若大于0，先查找表中是否有此类基金对象的记录
        client.setClient_balance(remain);//设置购买后的余额
        Connection conn = null;
        Buy_Fund buyFund;
        List<Buy_Fund> buy_funds = queryBuy_Fund(new Buy_Fund(fund.getFund_id(), client.getClient_id()));
        //执行（4.1）的事务
        //（4.1）创建一个Buy_Fund类，将基本信息存入，并执行以下事务：
        //        向buy_fund表中增加一条记录
        //        修改客户账户内余额
        //        结束事务，返回创建好的Buy_Fund类
        if (buy_funds.isEmpty()) {
            //客户没有购买过该产品
            try {
                conn = DBUtils.getConnection();
                //开始事务
                conn.setAutoCommit(false);
                buyFund = new Buy_Fund(fund.getFund_id(), client.getClient_id(), new Date(new java.util.Date().getTime()), quantity, "可用", 0.0);//默认数据
                int flag1 = qr.update(conn, "INSERT INTO finance.buy_fund(fund_id,client_id,buy_fund_time,buy_fund_quantity,buy_fund_assetstatus,buy_fund_earnings) VALUES (?,?,?,?,?,?)", buyFund.getFund_id(), buyFund.getClient_id(), buyFund.getBuy_fund_time(), buyFund.getBuy_fund_quantity(), buyFund.getBuy_fund_assetstatus(), buyFund.getBuy_fund_earnings());
                int flag2 = qr.update(conn, "UPDATE client SET client_balance=? where client_id=?", client.getClient_balance(), client.getClient_id());
                if (flag1 > 0 && flag2 > 0) {
                    //两个操作都成功
                    DbUtils.commitAndCloseQuietly(conn);//提交并关闭连接
                    return buyFund;
                } else {
                    //有一个操作不成功
                    DbUtils.rollbackAndCloseQuietly(conn);//回滚并关闭连接
                    return null;
                }
            } catch (SQLException e) {
                DbUtils.rollbackAndCloseQuietly(conn);
                throw new RuntimeException(e);
            }
        }
        //（4.2）执行以下事务：
        //        更新buy_fund对象中的quantity字段
        //        修改客户账户内余额
        //        结束事务，返回修改好的Buy_Fund类
        if (!buy_funds.isEmpty()) {
            //客户购买过该产品
            try {
                buyFund = buy_funds.get(0);//取出第一项购买基金记录，也只可能有一项记录
                conn = DBUtils.getConnection();
                //开始事务
                conn.setAutoCommit(false);
                quantity = buyFund.getBuy_fund_quantity() + quantity;//更新后的购买数量
                buyFund.setBuy_fund_quantity(quantity);
                int flag1 = qr.update(conn, "UPDATE buy_fund SET buy_fund_quantity=?", quantity);
                int flag2 = qr.update(conn, "UPDATE SET client_balance=? where client_id=?", client.getClient_balance(), client.getClient_id());
                if (flag1 > 0 && flag2 > 0) {
                    //两个操作都成功
                    DbUtils.commitAndCloseQuietly(conn);//提交并关闭连接
                    return buyFund;
                } else {
                    //有一个操作不成功
                    DbUtils.rollbackAndCloseQuietly(conn);//回滚并关闭连接
                    return null;
                }
            } catch (SQLException e) {
                DbUtils.rollbackAndCloseQuietly(conn);
                throw new RuntimeException(e);
            }
        }
        return null;//操作不成功
    }
}
